package Element;

import java.awt.*;
import java.util.*;

import Element.Geom.*;
import DistSys.*;

public class Group extends AbsElem implements Cloneable {
    public static AbsElem objActiveTemp;  //a developer's version of ActiveTemplate

    public Vector containedElemList;

    public Group() {
        containedElemList = new Vector(10,10);
    }
    public Object clone() {
        Group created = new Group();
        this.copyTo(created); // copy AbsElem attributes to created
        //created.setDftTemp(this.getDftTempName());
        //created.rel  = (ReliaInd) (this.rel.clone());
        //created.ckt  = (CktLaw) (this.ckt.clone());
        created.geom = (GroupGeom) (((GroupGeom)this.geom).clone());
        return created;
    }

    public int getType() { return SysConst.TYPE_GROUP; }

    public void draw(Graphics g) {
        int x = Math.min(geom.x1, geom.x2), y = Math.min(geom.y1, geom.y2);
        int width  = Math.abs(geom.x2-geom.x1);
        int height = Math.abs(geom.y2-geom.y1);

        Graphics2D g2 = (Graphics2D) g;

        float[] dashArray = {10.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f};
        BasicStroke dftBS = (BasicStroke) g2.getStroke();
        BasicStroke newBS = new BasicStroke(dftBS.getLineWidth(),
                                            dftBS.getEndCap(),
                                            dftBS.getLineJoin(),
                                            dftBS.getMiterLimit(),
                                            dashArray, // customized dash
                                            dftBS.getDashPhase());
        g2.setStroke(newBS);      //update stroke
        g.drawRect(x,y, width,height);
        g2.setStroke(dftBS);
    }

    // Dummy implementation of the abstract method since we inherit draw(g)
    public void draw(Graphics2D g2, double dist, double theta) { }

    // find contained elem from v;
    // v=Sys.screenElemList if this group is totally inside of the screen
    // otherwise v = Sys.elemList
    public void findContainedElemFrom(Vector candidate){
        AbsElem theElem;
        AbsElemGeom theGeom;
        this.containedElemList.removeAllElements();
        for(int i=0;i<candidate.size();i++){
            theElem = (AbsElem) candidate.elementAt(i);
            theGeom = theElem.getElemGeomObj();
            if( this.geom.frame.contains( theGeom.x1, theGeom.y1 ) &&
                this.geom.frame.contains( theGeom.x2, theGeom.y2 )  )
            {   this.containedElemList.add( theElem );
                theGeom.group = Sys.elemList.indexOf(this);
            }
        }//end of for
    }

    public Vector getContainedElemList(){ return containedElemList;}

    /**
     * Returns whether the data field with the given index "makes sense" for
     * this element type or not.
     *
     * @param index  a <code>int</code> specifying the index.
     *
     * @return  <code>true</code> if the data field "makes sense",
     *          <code>false</code> otherwise
     */
    public boolean getDataExists(int index) {
        // A switch is used here to be independent of the
        // AbsElem.DATA_* constant's real values.
        switch(index) {
            case AbsElem.DATA_ZONE:
            case AbsElem.DATA_LAYER:
            case AbsElem.DATA_RATED_POWER:
            case AbsElem.DATA_RATED_CURR:
            case AbsElem.DATA_ZONE_BUFFER0:
            case AbsElem.DATA_ZONE_BUFFER2:
            case AbsElem.DATA_ZONE_BUFFER4:
            case AbsElem.DATA_ZONE_BUFFER1:
            case AbsElem.DATA_ZONE_BUFFER3:
            case AbsElem.DATA_CAPITAL_COST:
            case AbsElem.DATA_OM_COST:
            case AbsElem.DATA_FONT_SIZE:
            case AbsElem.DATA_IN_OPT_LIB:
            case AbsElem.DATA_MAINT_DUR:
            case AbsElem.DATA_MAINT_RATE:
            case AbsElem.DATA_OPTIMIZABLE:
            case AbsElem.DATA_PHASE:
            case AbsElem.DATA_STUDY_AREA:
            case AbsElem.DATA_UPGRADE_COST:
            case AbsElem.DATA_YEAR:
                return true;
            default:
                return false;
        }
    }

    /**
     * Returns whether the result field with the given index "makes sense" for
     * this element type or not.
     *
     * @param index  a <code>int</code> specifying the index.
     *
     * @return  <code>true</code> if the result field "makes sense",
     *          <code>false</code> otherwise
     */
    public boolean getResultExists(int index) {
        // A switch is used here to be independent of the
        // AbsElem.RES_* constant's real values.
        switch(index) {
            case AbsElem.RES_QUERY_SCORE:
            case AbsElem.RES_QUERY_SCORE_PERC:
                return true;
            default:
                return false;
        }
    }
}